﻿/*
SINACOR - BMF&Bovespa
Arquivo: FinanceiroPendente.cs
Criado em: 23-jul-2010 10:46:59
Arquiteto Responsável: p-wgeneroso
*/
using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Common;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.Common.Exceptions;
using System.Linq;
using PSE.ProcessManager.Common.Process;
using System.Collections.ObjectModel;


namespace Sinacor.UI.Bovespa.ResumoFinanceiro.Presenter 
{
    public class FinanceiroPendente : BasePresenter<IFinanceiroPendente>
	{
		#region Atributos
		private Communication.FinanceiroPendente _communicationFinanceiroPendente;
		private Communication.ProcessoCalculoFinanceiro _communicationProcessoCalculoFinanceiro;
        private Communication.Calendario _communicationCalendario;
        private Communication.Cliente _communicationCliente;
        private Communication.ControleMovimentoOrdens _communicationControleMovimentoOrdens;

		private Model.Parameter.FiltroCalculoFinanceiro _filtroCalculoFinanceiro;
        private Model.Parameter.FiltroFinanceiroPendente _filtroFinanceiroPendente;
        private ModelCollection<Model.FinanceiroPendente> _listaFinanceiroPendente;
        private ProcessStatus _statusProcesso;
        private ModelCollection<Model.Calendario> _calendario;
        private Model.InformacoesMovimento _informacoesMovimento;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoCliente>> _listaTipoCliente;
		#endregion

        public FinanceiroPendente(IFinanceiroPendente view)
            :base(view)
        {
            this._communicationFinanceiroPendente = new Communication.FinanceiroPendente(this.Session);
            this._communicationProcessoCalculoFinanceiro = new Communication.ProcessoCalculoFinanceiro(this.Session);
            this._communicationCalendario = new Sinacor.UI.Bovespa.ResumoFinanceiro.Communication.Calendario(this.Session);
            this._communicationCliente = new Sinacor.UI.Bovespa.ResumoFinanceiro.Communication.Cliente(this.Session);
            this._communicationControleMovimentoOrdens = new Sinacor.UI.Bovespa.ResumoFinanceiro.Communication.ControleMovimentoOrdens(this.Session);

            this._communicationProcessoCalculoFinanceiro.CommunicationError += new EventHandler<CommunicationErrorEventArgs>(_communicationProcessoCalculoFinanceiro_CommunicationError);
            this._communicationProcessoCalculoFinanceiro.ProcessStatusReceived += new EventHandler<PSE.ProcessManager.Client.Process.ProcessStatusEventArgs>(_communicationProcessoCalculoFinanceiro_ProcessStatusReceived);
            this._communicationProcessoCalculoFinanceiro.ProcessamentoIniciado += new Action(_communicationProcessoCalculoFinanceiro_ProcessamentoIniciado);
            this._communicationProcessoCalculoFinanceiro.CalculoFinanceiroConcluido += new Action<ModelCollection<Sinacor.UI.Bovespa.ResumoFinanceiro.Model.CalculoFinanceiroResultado>>(_communicationProcessoCalculoFinanceiro_CalculoFinanceiroConcluido);
            this._communicationProcessoCalculoFinanceiro.Aborted += new EventHandler(_communicationProcessoCalculoFinanceiro_Aborted);

            this._filtroCalculoFinanceiro = new Sinacor.UI.Bovespa.ResumoFinanceiro.Model.Parameter.FiltroCalculoFinanceiro();
            this._filtroFinanceiroPendente = new Sinacor.UI.Bovespa.ResumoFinanceiro.Model.Parameter.FiltroFinanceiroPendente();
            this._listaFinanceiroPendente = new ModelCollection<Sinacor.UI.Bovespa.ResumoFinanceiro.Model.FinanceiroPendente>();
            this._statusProcesso = new ProcessStatus();
        }

		#region Propriedades
		
        public Model.Parameter.FiltroCalculoFinanceiro FiltroCalculoFinanceiro
		{
			get { return _filtroCalculoFinanceiro; }
			set { _filtroCalculoFinanceiro = value; }
		}

        public Model.Parameter.FiltroFinanceiroPendente FiltroFinanceiroPendente
        {
            get { return _filtroFinanceiroPendente; }
            set { _filtroFinanceiroPendente = value; }
        }

        public ModelCollection<Model.FinanceiroPendente> ListaFinanceiroPendente
        {
            get { return _listaFinanceiroPendente; }
            set { _listaFinanceiroPendente = value; }
        }

        public ProcessStatus StatusProcesso
        {
            get { return _statusProcesso; }
            set { _statusProcesso = value; }
        }

        public ModelCollection<Model.Calendario> Calendario
        {
            get
            {
                return _calendario;
            }
            set
            {
                _calendario = value;
            }
        }

        public Model.InformacoesMovimento InformacoesMovimento
        {
            get { return _informacoesMovimento; }
            set { _informacoesMovimento = value; }
        }

        public ObservableCollection<EnumWrapper<Model.Enum.TipoCliente>> ListaTipoCliente
        {
            get
            {
                return _listaTipoCliente;
            }
            set
            {
                _listaTipoCliente = value;
            }
        }

        public Model.Cliente ClienteAtual { get; set; }

		#endregion

		#region Métodos

        public override void Dispose()
        {
            _communicationProcessoCalculoFinanceiro.Disconnect();

            base.Dispose();
        }

        public void Inicializar()
        {
            this.CarregarCalendario();
            this.CarregarInformacaoMovimento();
            this.CarregarListaTipoCliente();
        }

		public void ConsultarFinanceirosPendentes()
		{
            try
            {
                this.StatusProcesso.Step = string.Empty;
                this.StatusProcesso.Progress = 0;

                View.AtualizarStatus();

                this.ListaFinanceiroPendente = this._communicationFinanceiroPendente.ConsultarFinanceirosPendentes(this.FiltroFinanceiroPendente);

                foreach (Model.FinanceiroPendente item in this.ListaFinanceiroPendente)
                {
                    item.Identificador = Guid.NewGuid();
                }

                View.AtualizarListaFinanceirosPendentes();
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
		}

		public void CalcularFinanceiros(bool calculaTudo)
		{
            bool confirma = false;
            
            try
            {
                foreach (Model.FinanceiroPendente item in this.ListaFinanceiroPendente)
                    item.ClearErrors();
                
                this.FiltroCalculoFinanceiro.CalculaTudo = calculaTudo;


                if (this.FiltroCalculoFinanceiro.CalculaTudo)
                {
                    confirma = View.ConfirmarCalculoFinanceiroTudo();
                }
                else
                {
                    if (this.FiltroCalculoFinanceiro.FinanceirosPendentes == null ||
                        this.FiltroCalculoFinanceiro.FinanceirosPendentes.Count == 0)
                    {
                        confirma = View.ConfirmaCalculaTudoNaoSelecionado();
                    }
                    else
                        confirma = View.ConfirmarCalculoFinanceiro();
                }
                
                if (confirma)
                {
                    if (this.FiltroCalculoFinanceiro.CalculaTudo && this._listaFinanceiroPendente != null)
                    {
                        this._listaFinanceiroPendente.Clear();
                        View.AtualizarListaFinanceirosPendentes();
                    }
                    
                    if (!_communicationProcessoCalculoFinanceiro.IsProcessRunning())
                    {
                        this.FiltroCalculoFinanceiro.Filtro = this._filtroFinanceiroPendente;
                        
                        View.PrepararControlesInicioProcesso();
                        this.AtualizarStatusInicioProcesso();

                        this.FiltroCalculoFinanceiro.MaquinaUsuario = System.Net.Dns.GetHostName();

                        _communicationProcessoCalculoFinanceiro.CalcularFinanceiros(this.FiltroCalculoFinanceiro);
                    }
                }
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
		}

        public void CancelarProcessamento()
        {
            try
            {
                if (View.ConfirmarCancelamento())
                    _communicationProcessoCalculoFinanceiro.Abort();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        public void VerificarCliente(string apelido)
        {
            this.ClienteAtual = null;

            try
            {
                Model.Parameter.FiltroCliente filtro = new Model.Parameter.FiltroCliente
                {
                    Apelido = apelido
                };

                this.ClienteAtual = _communicationCliente.ObterCliente(filtro);
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
        }

        public bool VerificarProcessamento()
        {
            return _communicationProcessoCalculoFinanceiro.IsProcessRunning();
        }

		/// 
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _communicationProcessoCalculoFinanceiro_CommunicationError(object sender, CommunicationErrorEventArgs e)
		{
            try
            {
                View.DesabilitarCancelamentoProcesso();
                View.AtualizarStatus();
                View.FinalizarExportacao();

                HandleException(e.Exception);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
		}

		/// 
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _communicationProcessoCalculoFinanceiro_ProcessStatusReceived(object sender, PSE.ProcessManager.Client.Process.ProcessStatusEventArgs e)
		{
            StatusProcesso.Step = e.Status.Step;
            StatusProcesso.Progress = e.Status.Progress;

            View.AtualizarStatus();
		}

        private void _communicationProcessoCalculoFinanceiro_ProcessamentoIniciado()
        {
            try
            {
                View.HabilitarCancelamentoProcesso();
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
        }

		/// 
		/// <param name="obj"></param>
		private void _communicationProcessoCalculoFinanceiro_CalculoFinanceiroConcluido(ModelCollection<Model.CalculoFinanceiroResultado> obj)
		{
            Model.FinanceiroPendente model = null;
            ValidationException validation = null;
            bool hasError = false;

            try
            {
                if (obj != null)
                {
                    foreach (Model.CalculoFinanceiroResultado item in obj)
                    {
                        model = this._listaFinanceiroPendente.SingleOrDefault(x => x.Identificador == item.FinanceiroPendente.Identificador);
                        
                        if (item.Sucesso)
                        {
                            View.RemoverRegistro(model);
                        }
                        else
                        {
                            hasError = true;

                            validation = new ValidationException();
                            validation.ValidationErrors.Add(item.Erro.ErrorNumber, item.Erro);

                            if (model != null)
                            {
                                model.AddError(validation);
                            }
                            else
                            {
                                if (item.FinanceiroPendente != null)
                                {
                                    item.FinanceiroPendente.Identificador = Guid.NewGuid();
                                    item.FinanceiroPendente.AddError(validation);
                                    View.InserirRegistro(item.FinanceiroPendente);
                                }
                            }
                        }
                    }
                }
                
                View.DesabilitarCancelamentoProcesso();
                View.AtualizarStatus();
                View.AtualizarListaFinanceirosPendentes();

                if (hasError)
                    View.InformarProcessoConcluidoComErros();
                else
                    View.InformarSucessoCalculoFinanceiro();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
		}

		/// 
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _communicationProcessoCalculoFinanceiro_Aborted(object sender, EventArgs e)
		{
            try
            {
                View.DesabilitarCancelamentoProcesso();
                View.AtualizarStatus();
                View.InformarCalculoFinanceiroCancelado();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
		}

        private void AtualizarStatusInicioProcesso()
        {
            StatusProcesso.Step = "Bovespa.ResumoFinanceiro.Message.PreparandoProcessamento";
            StatusProcesso.Progress = 0;

            View.AtualizarStatus();
        }

        private void CarregarCalendario()
        {
            ModelCollection<Model.Calendario> colecaoCalendario = null;

            try
            {
                colecaoCalendario = this._communicationCalendario.ConsultarCalendario();

                if (colecaoCalendario != null)
                {

                    var resultado =
                            from col in colecaoCalendario
                            orderby col.DataPregao descending
                            select col;

                    this.Calendario = new ModelCollection<Model.Calendario>(resultado);
                }

                View.AtualizarListaCalendario();
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
        }

        private void CarregarInformacaoMovimento()
        {
            try
            {
                _informacoesMovimento = this._communicationControleMovimentoOrdens.ObterInformacoesMovimento(new Model.DataMovimento());

                if (this._informacoesMovimento != null && this._filtroFinanceiroPendente != null)
                    this._filtroFinanceiroPendente.DataPregao = _informacoesMovimento.DataMovimento;

                View.AtualizarDataPregao();
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
        }

        private void CarregarListaTipoCliente()
        {
            _listaTipoCliente = EnumWrapper<Model.Enum.TipoCliente>.GetEnums(Model.Enum.TipoCliente.Cliente, Model.Enum.TipoCliente.Broker);

            View.AtualizarListaTipoCliente();
        }

		#endregion
	}

}
